package com.xuan.friend.manager;


import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.xuan.common.core.constants.CacheConstants;
import com.xuan.common.core.domain.PageRequest;
import com.xuan.common.redis.service.RedisService;
import com.xuan.friend.domain.message.vo.MessageTextVo;
import com.xuan.friend.mapper.message.UserMessageMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class MessageCacheManager {


    @Resource
    private RedisService redisService;

    @Resource
    private UserMessageMapper userMessageMapper;

    // ----------------------------用户消息缓存--------------------------------
    public Long getMessageListSize(Long userId) {
        String messageListKey = getMessageListKey(userId);
        return redisService.getListSize(messageListKey);
    }

    public void refreshUserMessageCache(Long userId) {
        // 两个缓存: 1)u:m:l:    2)m:d:
        List<MessageTextVo> messageTextVoList = userMessageMapper.listUserMessageVo(userId);
        if (CollUtil.isEmpty(messageTextVoList)) {
            return;
        }

        // u:m:l:
        List<Long> textIdList = messageTextVoList.stream().map(MessageTextVo::getTextId).toList();
        String messageListKey = getMessageListKey(userId);
        redisService.rightPushAll(messageListKey, textIdList);
        redisService.expire(messageListKey, CacheConstants.EXP, TimeUnit.HOURS);
        // m:d:
        Map<String, MessageTextVo> MessageTextVoMap = new HashMap<>();
        for (MessageTextVo messageTextVo : messageTextVoList) {
            String messageDetailKey = getMessageDetailKey(messageTextVo.getTextId());
            MessageTextVoMap.put(messageDetailKey, messageTextVo);
        }
        redisService.multiSet(MessageTextVoMap);
    }


    public List<MessageTextVo> getMessageTextVoList(PageRequest pageRequest, Long userId) {
        Integer pageNum = pageRequest.getPageNum();
        Integer pageSize = pageRequest.getPageSize();
        // 1. 计算下标
        long start = (long) (pageNum - 1) * pageSize;
        long end = start + pageSize - 1;     // redis的list类型是左闭右闭的
        List<Long> textIdList = redisService.getCacheListByRange(getMessageListKey(userId), start, end, Long.class);
        // 2. 根据 textId 获取消息详情
        List<MessageTextVo> messageTextVoList = assembleMessageTextVoList(textIdList);
        if (CollUtil.isEmpty(messageTextVoList)) {
            // redis 数据存在异常 或 没有数据, 从数据库中查询
            messageTextVoList = getMsgTextVoListByDB(pageRequest, userId);
            refreshUserMessageCache(userId);    // 刷新数据到缓存中
        }
        return messageTextVoList;
    }

    public void deleteCache(Long textId, Long userId) {
        String messageListKey = getMessageListKey(userId);
        redisService.removeForList(messageListKey, textId);
        String messageDetailKey = getMessageDetailKey(textId);
        redisService.deleteObject(messageDetailKey);
    }


    private List<MessageTextVo> assembleMessageTextVoList(List<Long> textIdList) {
        if (CollUtil.isEmpty(textIdList)) {
            return null;
        }
        // 拼接竞赛详情 key, 利用一条命令进行多个查询
        List<String> messageDetailKeyList = new ArrayList<>();
        for (Long textId : textIdList) {
            messageDetailKeyList.add(getMessageDetailKey(textId));
        }
        List<MessageTextVo> MessageTextVoList = redisService.multiGet(messageDetailKeyList, MessageTextVo.class);
        CollUtil.removeNull(MessageTextVoList);
        if (CollUtil.isEmpty(MessageTextVoList) || MessageTextVoList.size() != textIdList.size()) {
            // redis 数据存在异常,某些数据查询不到
            return null;
        }
        return MessageTextVoList;
    }


    private List<MessageTextVo> getMsgTextVoListByDB(PageRequest pageRequest, Long userId) {
        PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize());
        return userMessageMapper.listUserMessageVo(userId);
    }

    private String getMessageListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST_KEY + userId;
    }

    private String getMessageDetailKey(Long textId) {
        return CacheConstants.MESSAGE_DETAIL_KEY + textId;
    }


}
